﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;

namespace eslib.nnp5
{
    /// <summary>
    /// 连接管理器
    /// </summary>
    public abstract class ConnectorManager
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="autoReConnect">自动重新连接,服务器应设置为false</param>
        public ConnectorManager(bool autoReConnect)
        {
            AutoReConnect = autoReConnect;
        }



        /// <summary>
        /// 推入一个新的连接器(未连接的)
        /// </summary>
        /// <param name="connector">必需未连接</param>
        public void PushConnector(Connector connector)
        {
            //连接
            beginConnect(connector);
        }




        /// <summary>
        /// 推入一个监听器，自动调用listenStart()
        /// </summary>
        /// <param name="listener"></param>
        public void PushServerListener(ServerListener listener)
        {
            listener.NewConnectionEvent += Listener_NewConnectionEvent;
            listener.listenStart();
        }



        /// <summary>
        /// 创建AppUser
        /// </summary>
        /// <param name="connector"></param>
        /// <returns></returns>
        public abstract IAppBase CreateAppUser(Connector connector);





        #region 内部实现



        private void beginConnect(Connector connector)
        {
            if (AutoReConnect)
            {
                connector.EnableReconnectOnConnectFailEvent = true;
            }
            connector.ConnectSuccessEvent += Connector_ConnectSuccessEvent;
            connector.beginConnect();

            Debug.WriteLine("Begin connect...");
        }

        private void Connector_ConnectSuccessEvent(Connector connector)
        {
            //入库
            addConnector(connector, CreateAppUser(connector));

            Debug.WriteLine("Connect success");
        }


        /// <summary>
        /// 新连接进入事件
        /// </summary>
        /// <param name="connector"></param>
        private void Listener_NewConnectionEvent(Connector connector)
        {
            //入库
            addConnector(connector, CreateAppUser(connector));

            Debug.WriteLine("Accept connect.");
        }




        /// <summary>
        /// 有连接器断开连接
        /// </summary>
        /// <param name="connector"></param>
        /// <param name="message"></param>
        private void Connector_DisconnectEvent(Connector connector, string message)
        {
            //出库
            removeConnector(connector);

            if (AutoReConnect)
            {
                //重新连接
                Connector newConn = connector.Clone();
                PushConnector(newConn);
            }
        }







        void addConnector(Connector connector, IAppBase appUser)
        {
            //监听断开连接事件
            connector.DisconnectEvent += Connector_DisconnectEvent;
            ConnectorTable[connector] = appUser;

            //事件通知
            Task.Run(() =>
            {
                OnlineAppsCountChangeEvent?.Invoke(AppUserCount);
            });
        }

        void removeConnector(Connector connector)
        {
            ConnectorTable.Remove(connector);

            //事件通知
            Task.Run(() =>
            {
                OnlineAppsCountChangeEvent?.Invoke(AppUserCount);
            });
        }



        /// <summary>
        /// 自动重连
        /// </summary>
        public bool AutoReConnect { get; set; }


        /// <summary>
        /// 已连接的AppUser对象集
        /// </summary>
        public List<IAppBase> AppUsers
        {
            get
            {
                List<IAppBase> res = new List<IAppBase>();
                foreach (var appuser in ConnectorTable.Values)
                {
                    res.Add((IAppBase)appuser);
                }
                return res;
            }
        }

        /// <summary>
        /// 关闭所有AppUser，并设置AutoReConnect为false
        /// </summary>
        public void CloseAppUsers()
        {
            AutoReConnect = false;

            foreach (var app in AppUsers)
            {
                try
                {
                    app.Close();
                }
                catch { }
            }
        }


        /// <summary>
        /// AppUser数量
        /// </summary>
        public int AppUserCount
        {
            get
            {
                return ConnectorTable.Count;
            }
        }



        Hashtable ConnectorTable
        {
            get
            {
                lock (this)
                {
                    return table;
                }
            }
        }
        private Hashtable table = new Hashtable();


        #endregion


        /// <summary>
        /// [异步事件]在线AppUser数量变化时引发
        /// </summary>
        public event OnlineAppsCountChangeEventDelegate OnlineAppsCountChangeEvent;
    }


    /// <summary>
    /// 在线AppUser数量变化事件
    /// </summary>
    /// <param name="count"></param>
    public delegate void OnlineAppsCountChangeEventDelegate(int count);


}
